package com.vdong.redis.data.core.json.ops.impl;

import com.vdong.redis.data.core.json.DBExecutor;
import com.vdong.redis.data.core.json.FastJsonRedisTemplate;
import com.vdong.redis.data.core.json.ops.FastJsonBoundHashOperations;
import org.springframework.data.redis.connection.DataType;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.ScanOptions;

import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.TimeUnit;


/**
 * ops覆盖类，可提供原先ops没有的方法
 *
 * @author <a href="mailto:zhudelie@zuozh.com">zhudelie</a>
 * @since JDK 1.6
 * create on 2017年3月31日
 * Copyright 2017 ZZJR All Rights Reserved.
 */
public class FastJsonBoundHashOperationsImpl<K, HK, HV> extends OperationsAware<K, Object> implements FastJsonBoundHashOperations<K, HK, HV> {

    private BoundHashOperations<K, HK, HV> ops;

    public FastJsonBoundHashOperationsImpl(BoundHashOperations<K, HK, HV> ops, FastJsonRedisTemplate<K, Object> template) {
        super(template);
        this.ops = ops;
    }

    private BoundHashOperations getOps() {
        return ops;
    }

    /**
     * 获得当前key
     */

    public K getKey() {
        return (K) getOps().getKey();
    }

    /**
     * 获得当前存储的类型
     */

    public DataType getType() {
        // TODO Auto-generated method stub
        return getOps().getType();
    }

    /**
     * 获得过期时间
     */

    public Long getExpire() {
        // TODO Auto-generated method stub
        return getOps().getExpire();
    }

    /**
     * 设置过期时间
     */

    public Boolean expire(long timeout, TimeUnit unit) {
        // TODO Auto-generated method stub
        return getOps().expire(timeout, unit);
    }

    /**
     * 设置过期日期
     */

    public Boolean expireAt(Date date) {
        // TODO Auto-generated method stub
        return getOps().expireAt(date);
    }

    /**
     * 撤销过期时间
     */

    public Boolean persist() {
        // TODO Auto-generated method stub
        return getOps().persist();
    }

    /**
     * 重新设置key
     */

    public void rename(K newKey) {
        getOps().rename(newKey);
    }

    /**
     * 删除hashkey
     */

    public Long delete(Object... keys) {
        // TODO Auto-generated method stub
        return getOps().delete(keys);
    }

    /**
     * 包含hashkey
     */

    public Boolean hasKey(Object key) {
        // TODO Auto-generated method stub
        return getOps().hasKey(key);
    }

    /**
     * 根据hashkey得到value
     */

    public HV get(Object key) {
        // TODO Auto-generated method stub
        return (HV) getOps().get(key);
    }

    /**
     * 根据多个hashkey得到多个value
     */

    public List<HV> multiGet(Collection<HK> keys) {
        // TODO Auto-generated method stub
        return (List<HV>) getOps().multiGet(keys);
    }

    /**
     * 指定key自增指定大小
     */

    public Long increment(HK key, long delta) {
        // TODO Auto-generated method stub
        return getOps().increment(key, delta);
    }

    /**
     * 指定key自增指定大小
     */

    public Double increment(HK key, double delta) {
        // TODO Auto-generated method stub
        return getOps().increment(key, delta);
    }

    /**
     * 得到所有hashkey
     */

    public Set<HK> keys() {
        // TODO Auto-generated method stub
        return getOps().keys();
    }

    /**
     * 得到个数
     */

    public Long size() {
        return getOps().size();
    }

    /**
     * 设置多个值
     */

    public void putAll(Map<? extends HK, ? extends HV> m) {
        getOps().putAll(m);
    }

    /**
     * 设置值
     */

    public void put(HK key, HV value) {
        getOps().put(key, value);
    }

    /**
     * 设置值，如果该hashkey下的值不存在
     */

    public Boolean putIfAbsent(HK key, HV value) {
        // TODO Auto-generated method stub
        return getOps().putIfAbsent(key, value);
    }

    /**
     * 得到所有值
     */

    public List<HV> values() {
        // TODO Auto-generated method stub
        return getOps().values();
    }

    /**
     * 得到所有key和值
     */

    public Map<HK, HV> entries() {
        // TODO Auto-generated method stub
        return getOps().entries();
    }

    /**
     * 得到游标
     */

    public Cursor<Entry<HK, HV>> scan(ScanOptions options) {
        // TODO Auto-generated method stub
        return getOps().scan(options);
    }

    @Deprecated
    public void put(HK hashKey, HV value, DBExecutor<HV> db) {
        put(hashKey, value, db, null, null);
    }

    @Deprecated
    public HV get(HK hashKey, DBExecutor<HV> db) {
        return get(hashKey, db, null, null);
    }

    /**
     * 根据hashkey，获得指定类型的值
     *
     * @param hashKey
     * @param type
     * @return
     */
    public <T> T get(HK hashKey, Class<T> type) {
        template.setConvertType(type);
        return (T) get(hashKey);
    }

    @Deprecated
    public <T> T get(HK hashKey, Class<T> type, DBExecutor<T> db) {
        return get(hashKey, type, db, null, null);
    }

    @Deprecated

    public void put(HK hashKey, HV value, DBExecutor<HV> db, Long timeout, TimeUnit unit) {
        boolean needEx = false;
        if (timeout != null) {
            if (unit == null) {
                unit = TimeUnit.SECONDS;
            }
            needEx = !template.hasKey(this.getKey());
        }
        getOps().put(hashKey, value);
        if (needEx) {
            expire(timeout, unit);
        }
        db.execute(hashKey, value);
    }

    @Deprecated

    public HV get(HK hashKey, DBExecutor<HV> db, Long timeout, TimeUnit unit) {
        HV v = get(hashKey);
        if (v == null) {
            v = db.execute(getKey(), hashKey);
            if (v != null) {
                put(hashKey, v);
                if (timeout != null) {
                    if (unit == null) {
                        unit = TimeUnit.SECONDS;
                    }
                    expire(timeout, unit);
                }
            }
        }
        return v;
    }

    @Deprecated

    public <T> T get(HK hashKey, Class<T> type, DBExecutor<T> db, Long timeout, TimeUnit unit) {
        T v = get(hashKey, type);
        if (v == null) {
            v = db.execute(getKey(), hashKey);
            if (v != null) {
                getOps().put(hashKey, v);
                if (timeout != null) {
                    if (unit == null) {
                        unit = TimeUnit.SECONDS;
                    }
                    expire(timeout, unit);
                }
            }
        }
        return v;
    }
}
